package org.medusa.module;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class Module {

	private static Map<Integer, Module> id_mod_link = new HashMap<Integer, Module>();
	private static Map<Class<?>, Module> class_mod_link = new HashMap<Class<?>, Module>();
	private static AtomicInteger index = new AtomicInteger(1);
	
	private int mod_id = 0;
	private boolean initialized = false;

	protected Module() {
		
	}
	
	protected static boolean register(Module mod) {
		boolean ret =false;
		
		if (mod != null) {
			if (!Module.class_mod_link.containsKey(mod
							.getClass().getName())) {
				mod.set_mod_id(Module.index.addAndGet(1));
				System.err.println("module " + mod.getClass().getName()
						+ " register success");
				ret = true;
			}
			else
				System.err.println("module " + mod.getClass().getName()
						+ " can't repeat register!");
		}
		
		return ret;
	}

	private void set_mod_id(int mod_id) {
		this.mod_id = mod_id;
	}

	public int ModID() {
		return this.mod_id;
	}

	public String ModName() {
		return this.getClass().getName();
	}

	protected void set_started(boolean val) {
		this.initialized = val;
	}

	public boolean IsStarted() {
		return this.initialized;
	}
	
	//public static void Add() {}

	/*
	 * public static void Starup() {
	 * 
	 * }
	 */

	public static void Restart() {
		Iterator<Module> it = Module.id_mod_link.values().iterator();
		while (it.hasNext()) {
			Module mod = it.next();
			if (mod != null)
				mod.set_started(mod.event_restart() == null);
		}
	}

	public static void Shutdown() {
		Iterator<Module> it = Module.id_mod_link.values().iterator();
		while (it.hasNext()) {
			Module mod = it.next();
			if (mod != null) {
				mod.event_shutdown();
				mod.set_started(false);
			}
		}
		Module.id_mod_link.clear();
		Module.class_mod_link.clear();
	}
	/*
	private static int todo_event = 0;

	protected static void require_start(Module mod) {
		if (mod != null && Module.todo_event == 0) {
			Module.todo_event = mod.ModID();
		} else
			System.err.println();
	}*/

	public static Module Get(int mod_id) {
		return Module.id_mod_link.get(mod_id);
	}

	@SuppressWarnings("unchecked")
	public static <T extends Module> T Query(Class<T> classType) {
		// Module mod = null;
		// Constructor<?> cons = null;
		if (!Module.class_mod_link.containsKey(classType)) {
			try {
				Constructor<?> cons = classType.getConstructor();
				Module mod = (Module) cons.newInstance();
				if (mod != null && Module.class.isInstance(mod) && Module.register(mod)) {
					
					//System.err.println("module " + mod.getClass().getName()
					//		+ " created.");
					Error err = mod.event_startup();
					if (err == null) {
						mod.set_started(true);
						System.err.println("module " + mod.getClass().getName() + " startup success");
						Module.id_mod_link.put(mod.ModID(), mod);
						Module.class_mod_link.put(mod.getClass(), mod);
					} else
						System.err.println("module " + mod.getClass().getName() + " startup failed");
				}
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}

		return (T) Module.class_mod_link.get(classType);
	}

	
	/*
	 * @SuppressWarnings("unchecked") public MOD Instance() { return (MOD) this;
	 * }
	 */

	// public abstract void Init();
	/*
	public Error Starup() {
		ModuleController.require_start(this);
		return null;
	}

	public void Restart() {

	}

	public void Shutdown() {

	}*/

	// protected abstract Error event_load_config();//不允许嵌套初始化

	protected abstract Error event_startup();

	protected abstract Error event_restart();

	protected abstract Error event_shutdown();
}
